home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************\
- *
- * Apple Macintosh Developer Technical Support
- *
- * Main program file
- *
- * Program: ColorImage
- * File: ColorImage.c
- *
- * by: Forrest Tanaka
- *
- * Copyright © 1988-1992 Apple Computer, Inc.
- * All rights reserved.
- *
- \******************************************************************************/
-
-
- /******************************************************************************\
- * Header Files
- \******************************************************************************/
-
- #ifndef THINK_C
- #include <Desk.h>
- #include <DiskInit.h>
- #include <Errors.h>
- #include <Fonts.h>
- #include <Menus.h>
- #include <Resources.h>
- #include <ToolUtils.h>
- #endif
-
- #include <AppleEvents.h>
- #include <GestaltEqu.h>
- #include <Packages.h>
- #include <Palettes.h>
- #include <Traps.h>
-
- #include "EmergMem.h"
- #include "Exceptions.h"
- #include "ColorReset.h"
- #include "MenuHandler.h"
- #include "PictDocument.h"
- #include "WindowPositioner.h"
-
-
- /******************************************************************************\
- * Constants
- \******************************************************************************/
-
- /* Disk initialization */
- #define kSysAlertLeft 80 /* Left coord of DIBadMount alert in screen coords */
- #define kSysAlertTop 80 /* Top coord of DIBadMount alert in screen coords */
-
- /* EqualString convenience constants */
- #define kCaseSens true /* Pass to EqualString for case-sensitive check */
- #define kDiacSens true /* Pass to EqualString for diacritical-sens. check */
-
- /* Constants for checking on command-. */
- #define kMaskModifiers 0xFE00 /* Mask for modifiers w/o command key */
- #define kMaskASCII1 0x00FF0000 /* get the key out of the ASCII1 byte */
- #define kMaskASCII2 0x000000FF /* get the key out of the ASCII2 byte */
-
- /* Miscellaneous */
- #define kMinWindSize 128 /* Minimum size of a window */
- #define kMaxSleepTime 60 /* # ticks to wait between minor switches */
- #define kBecomingActive true /* Pass to DoActivateEvt; app becoming active */
-
-
- /******************************************************************************\
- * Macros
- \******************************************************************************/
-
- /* Return status of bth bit of m */
- #define btst(m,b) ((m) & (1L << (b)))
-
-
- /******************************************************************************\
- * Global Variables
- \******************************************************************************/
-
- Boolean gHasWNE; /* True if WaitNextEvent is implemented */
- Boolean gQuitting; /* True if user requested that this app quit */
- Boolean gWereInFront; /* True if this application is frontmost */
- Boolean gFixMenus; /* True if menus need fixing */
- Boolean gHasAppleEvents; /* True if Apple Events implemented */
- Boolean gHasCoolSF; /* True if 7.0 Standard File routines available */
-
-
- /******************************************************************************\
- * Private Function Prototypes
- \******************************************************************************/
-
- int main(void);
-
- void StartUp(void);
-
- void ShutDown(void);
-
- void EventLoop(void);
-
- long CalcSleepTime(void);
-
- void DoMouseDown(
- EventRecord *anEvent);
-
- void DoKeyDown(
- EventRecord *anEvent);
-
- void DoDiskEvt(
- EventRecord *anEvent);
-
- pascal OSErr HandleAEquit(
- AppleEvent *quitAppleEvent,
- AppleEvent *reply,
- long handlerRefCon);
-
- OSErr DoneRequiredParams(
- AppleEvent *anAppleEvent);
-
- Boolean IsDAWindow(
- WindowPtr aWindow);
-
- void DoWindowDrag(
- EventRecord *anEvent,
- WindowPtr clickedWindow);
-
- void DoWindowGrow(
- EventRecord *anEvent,
- WindowPtr clickedWindow);
-
- void DoContentClick(
- EventRecord *anEvent,
- WindowPtr clickedWindow);
-
- void DoActivateEvt(
- WindowPtr eventWind,
- Boolean becomingActive);
-
- void DoWindowClose(
- EventRecord *anEvent,
- WindowPtr eventWindow);
-
- short MaxToolboxTrap(void);
-
- TrapType GetTrapType(
- short theTrap);
-
-
- /******************************************************************************\
- * Public: main - Entry point to this application
- *
- * After the heap is initialized by allocating several master pointer blocks and
- * expanding the application’s heap to its maximum size, StartUp is called to
- * complete initialization. The user is asked to open a Picture Document, and
- * then the main event loop is entered.
- \******************************************************************************/
-
- int main()
- {
- /* Prepare the heap */
- MaxApplZone();
- MoreMasters();
- MoreMasters();
- MoreMasters();
- MoreMasters();
- MoreMasters();
- MoreMasters();
- MoreMasters();
- MoreMasters();
-
- /* Initialize the application */
- StartUp();
-
- /* Ask the user for a Picture Document to open */
- (void)DoOpenPictDoc();
-
- /* Execute the main event loop */
- EventLoop();
-
- /* Shut down the application */
- ShutDown();
-
- /* Return the ANSI way */
- return 0;
- }
-
-
- /******************************************************************************\
- * StartUp - Do whatever has to be done to initialize the application
- *
- * This routine is called after the heap is initialized to initialize the
- * application. This involves initializing the toolbox, emergency memory,
- * loading up the menus, validating the current environment, and initializing
- * global variables. If any errors occur while doing this, StartUp displays
- * an alert telling the user what the error was and then ExitToShell is called.
- * This is an unusual way to react to errors, and I only do it here because it’s
- * so early in execution that there really isn’t much else that can be done.
- *
- * See EmergMem.h in this application for details about emergency memory.
- \******************************************************************************/
-
- static void StartUp()
- {
- short result; /* Result of alert; ignored */
- long aeAttrs; /* AppleEvent attributes */
- long sfAttrs; /* Standard File attributes */
- OSErr error;
- ExceptionRec exception;
- long msgType;
- long msgCode;
-
- if (ExceptionEntry( /*<*/&exception, /*<*/&msgType, /*<*/&msgCode ))
- {
- result = ShowAlert( kStopAlert, rOKAlertID, msgType, msgCode );
- ExitToShell();
- }
-
- /* Initialize the toolbox */
- InitGraf( &thePort );
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs( nil );
-
- /* Initialize emergency memory */
- InitEmergMem();
- if (FailLowMemory( 0 ))
- Exception( &exception, rMemErrMessages, kMemErrAppOpenMsg );
-
- /* Initialize the menus */
- error = StartMenus();
- if (error == memFullErr || FailLowMemory( 0 ))
- Exception( &exception, rMemErrMessages, kMemErrAppOpenMsg );
- else if (error == resNotFound)
- Exception( &exception, rResErrMessages, kResErrAppDamageMsg );
- else if (error == dsSysErr)
- Exception( &exception, rMiscErrMessages, kMiscErrUnknownMsg );
-
- /* Load and lock the disk-initialization package */
- DILoad();
-
- /* See if WaitNextEvent is implemented */
- gHasWNE = TrapExists( _WaitNextEvent );
-
- /* Check for the fancier capabilities */
- error = Gestalt( gestaltAppleEventsAttr, /*<*/&aeAttrs );
- if (error != noErr)
- gHasAppleEvents = false;
- else
- gHasAppleEvents = btst( aeAttrs, gestaltAppleEventsPresent );
- error = Gestalt( gestaltStandardFileAttr, /*<*/&sfAttrs );
- if (error != noErr)
- gHasCoolSF = false;
- else
- gHasCoolSF = btst( sfAttrs, gestaltStandardFile58 );
-
- /* Install the AppleEvent handler */
- if (gHasAppleEvents)
- {
- error = AEInstallEventHandler( kCoreEventClass, kAEQuitApplication,
- (EventHandlerProcPtr)HandleAEquit, 0, false );
- if (error == memFullErr || FailLowMemory( 0 ))
- Exception( &exception, rMemErrMessages, kMemErrAppOpenMsg );
- else if (error != noErr)
- Exception( &exception, rMiscErrMessages, kMiscErrUnknownMsg );
- }
- }
-
-
- /******************************************************************************\
- * ShutDown - Do whatever has to be done to shut down the application
- *
- * This routine is called when the application is about to shut down. It calls
- * ExitGraphics and ExitPrinting to shut down Sarano graphics and printing.
- \******************************************************************************/
-
- static void ShutDown()
- {
- }
-
-
- /******************************************************************************\
- * EventLoop - Main event loop for this application
- *
- * This is the main event loop of this application. During every iteration of
- * the event loop, the menus are kept up-to-date. Also, NoEmergMem is called to
- * detect whether the emergency memory was used. If it was, then RecoverEmergMem
- * is called in an attept to get it back. If it can’t, then some commands could
- * be disabled until the memory can be recovered.
- \******************************************************************************/
-
- static void EventLoop()
- {
- EventRecord anEvent; /* An incoming event */
- Boolean gotEvent; /* True if a non-null event was received */
- WindowPtr lastWindow; /* Pointer to front window during last iteration */
- WindowPtr currWindow; /* Pointer to the current front window */
- WindowPtr eventWindow; /* Window involved in an incoming event */
- Byte osEvtKind; /* Kind of OSEvt; mouse-moved or suspend/resume */
-
- gWereInFront = true;
- gQuitting = false;
- gFixMenus = true;
- lastWindow = nil;
- InitCursor();
-
- /* We loop until gQuitting is true */
- while (!gQuitting)
- {
- /* Try to reallocate emergency memory if it’s been used */
- if (NoEmergMem())
- RecoverEmergMem();
-
- /* Fix the menus to reflect current conditions */
- currWindow = FrontWindow();
- if (currWindow != lastWindow || gFixMenus)
- {
- FixMenus();
- lastWindow = currWindow;
- gFixMenus = false;
- }
-
- /* It’s time to get and examine an event */
- if (gHasWNE)
- gotEvent = WaitNextEvent( everyEvent, /*<*/&anEvent,
- CalcSleepTime(), nil );
- else
- {
- SystemTask();
- gotEvent = GetNextEvent( everyEvent, /*<*/&anEvent );
- }
- if (gotEvent)
- switch (anEvent.what)
- {
- case mouseDown:
- DoMouseDown( &anEvent );
- break;
- case keyDown:
- case autoKey:
- DoKeyDown( &anEvent );
- break;
- case updateEvt:
- DoUpdateEvt( &anEvent );
- break;
- case diskEvt:
- DoDiskEvt( &anEvent );
- break;
- case activateEvt:
- DoActivateEvt( (WindowPtr)anEvent.message,
- anEvent.modifiers & activeFlag );
- break;
- case kHighLevelEvent:
- (void)AEProcessAppleEvent( &anEvent );
- break;
- case osEvt:
- osEvtKind = (anEvent.message >> 24) & 0x0FF;
- if (osEvtKind == suspendResumeMessage)
- {
- /* It’s a suspend/resume event; suspend or resume? */
- eventWindow = FrontWindow();
- if ((anEvent.message & 1) != 0)
- {
- /* Resume event; set the cursor and activate front window */
- InitCursor();
- if (eventWindow != nil)
- DoActivateEvt( eventWindow, kBecomingActive );
- gWereInFront = true;
- }
- else
- {
- /* Suspend event; deactivate the front window */
- if (eventWindow != nil)
- DoActivateEvt( eventWindow, !kBecomingActive );
- gWereInFront = false;
- }
- }
- break;
- }
- }
- }
-
-
- /******************************************************************************\
- * CalcSleepTime - Calculate the number of ticks for WaitNextEvent to sleep
- *
- * WaitNextEvent takes a parameter that specifies the number of ticks that this
- * application allows WaitNextEvent to service other open applications. This is
- * just a guideline; the actual amount of time that WaitNextEvent takes could be
- * shorter or longer than our specification, depending on how heavy the system
- * load is and on how long other applications take.
- *
- * If the front window is a desk accessory window, CalcSleepTime returns 0 which
- * specifies that this application wants as much time as possible. Under
- * MultiFinder, desk accessories are normally running in the DA Handler layer,
- * so this really doesn’t matter that much. Under system software version 7.0,
- * desk accessories never run in our layer, so this code never gets executed.
- \******************************************************************************/
-
- static long CalcSleepTime()
- {
- long sleepTime; /* Number of ticks to sleep */
-
- if (IsDAWindow( FrontWindow() ))
- sleepTime = 0;
- else
- sleepTime = kMaxSleepTime;
-
- return sleepTime;
- }
-
-
- /******************************************************************************\
- * DoMouseDown - Mouse-down event dispatcher
- *
- * When a mouseDown event is received in the main event loop, this routine is
- * called to determine which area on the screens the mouseDown was, and to
- * dispatch to the appropriate routine to handle mouseDown events in that area.
- * The mouseDown event is passed in the anEvent parameter.
- *
- * See MenuHandler.h for routines that handle mouse-down events in the menu bar.
- \******************************************************************************/
-
- static void DoMouseDown(
- EventRecord *anEvent) /* Contains mouse-down event */
- {
- short clickArea; /* Area of the screen that was clicked */
- WindowPtr eventWindow; /* Pointer the clicked window, if any */
-
- /* Find clicked area of screen or window */
- clickArea = FindWindow( anEvent->where, /*<*/&eventWindow );
-
- /* Jump to mouseDown-handling routine appropriate for screen area */
- switch (clickArea)
- {
- case inMenuBar:
- DoMenuChoice( MenuSelect( anEvent->where ) );
- break;
- case inSysWindow:
- SystemClick( anEvent, eventWindow );
- break;
- case inContent:
- DoContentClick( anEvent, eventWindow );
- break;
- case inDrag:
- DoWindowDrag( anEvent, eventWindow );
- break;
- case inGrow:
- DoWindowGrow( anEvent, eventWindow) ;
- break;
- case inGoAway:
- DoWindowClose( anEvent, eventWindow );
- break;
- default:
- break;
- }
- }
-
-
- /******************************************************************************\
- * DoKeyDown - Key-down event dispatcher
- *
- * When a keyDown or autoKey event is received in the main event loop, this
- * routine is called to determine whether key is a command-key equivalent for a
- * menu item or not. If the command key isn’t down, then the key stroke is
- * ignored. Otherwise, MenuKey is called to get the menu ID and item number
- * of the menu item that corresponds to the command key, if any. Then
- * DoMenuChoice is called to dispatch to the appropriate routine for the chosen
- * menu item. The keyDown or autoKey event is passed in anEvent.
- \******************************************************************************/
-
- static void DoKeyDown(
- EventRecord *anEvent) /* Contains the key-down event */
- {
- char theKey; /* ASCII code of key that was pressed */
-
- /* Get the ASCII code of the pressed key */
- theKey = anEvent->message & charCodeMask;
-
- /* If anEvent was keyDown and command key was down, it’s menu command */
- if (anEvent->what == keyDown && (anEvent->modifiers & cmdKey))
- DoMenuChoice( MenuKey( theKey ) );
- }
-
-
- /******************************************************************************\
- * DoDiskEvt - Handle a disk-insert event
- *
- * This routine is called whenever this application receives an event indicating
- * that a disk was inserted. If the disk can’t be mounted, the message field of
- * the event reflects the error, and we call DIBadMount to allow the user to
- * format the disk.
- \******************************************************************************/
-
- static void DoDiskEvt(
- EventRecord *anEvent) /* Disk-insert event */
- {
- Point cornerPoint; /* Top-left corner of DIBadMount alert */
-
- if (hiWord( anEvent->message ) != noErr)
- {
- SetPt( /*<*/&cornerPoint, kSysAlertLeft, kSysAlertTop );
- (void)DIBadMount( cornerPoint, anEvent->message );
- }
- }
-
-
- /******************************************************************************\
- * Private: HandleAEquit - Handler for 'quit' AppleEvent
- *
- * This is the AppleEvent handler for the 'quit' AppleEvent as passed in the
- * quitAppleEvent parameter by the AppleEvent Manager. The DoQuit routine is
- * called which causes this application to quit at the start of the next
- * iteration of the main event loop.
- *
- * Though the quit AppleEvent doesn’t contain any parameters, the standard thing
- * to do in reaction to any AppleEvent is to check to see if there are any
- * required parameters in the AppleEvent that this routine doesn’t recognise.
- * DoneRequiredParms checks for this condition and returns an error if there are
- * in fact required parameters in the AppleEvent or if some other error occurs
- * during the check.
- \******************************************************************************/
-
- static pascal OSErr HandleAEquit(
- AppleEvent *quitAppleEvent, /* Contains the ‘quit’ AppleEvent */
- AppleEvent *reply, /* Returns reply; ignored */
- long handlerRefCon) /* Application-defined parameter; ignored */
- {
- #pragma unused(reply,handlerRefCon)
- OSErr error;
-
- /* quit AE has no parms, but check in case the client requires any */
- error = DoneRequiredParams( quitAppleEvent );
- if (error == noErr)
- /* No extra parameters; handle Quit command */
- DoQuit();
-
- return error;
- }
-
-
- /******************************************************************************\
- * DoneRequiredParams - Done processing required params; OK?
- *
- * DoneRequiredParams checks to see if the AppleEvent specified by the
- * anAppleEvent parameter has any required parameters that we haven’t yet
- * processed. If there aren’t any left, then noErr is returned. If there are
- * required parameters that haven’t been processed yet, then errAEEventNotHandled
- * is returned. If any other errors occur, then that error code is returned.
- \******************************************************************************/
-
- static OSErr DoneRequiredParams(
- AppleEvent *anAppleEvent) /* AppleEvent being checked */
- {
- DescType typeCode; /* Type of AppleEvent attribute found; ignored */
- Size actualSize; /* Actual size of parameters; ignored */
- OSErr error;
-
- /* Are there any required parameters in AppleEvent we didn’t process? */
- error = AEGetAttributePtr(
- anAppleEvent,
- keyMissedKeywordAttr,
- typeWildCard,
- /*<*/&typeCode,
- nil,
- 0,
- /*<*/&actualSize );
- if (error == errAEDescNotFound)
- /* No required parameters left, so no error */
- error = noErr;
- else if (error == noErr)
- /* There was at least one required parameter we didn’t process */
- error = errAEEventNotHandled;
-
- return error;
- }
-
-
- /******************************************************************************\
- * Public: DoQuit
- *
- * Each open window is checked to see what kind it is. If a window is a
- * Document window, DoCloseDoc is called to close it. If the window is a
- * desk accessory’s window, then CloseDeskAcc is called to close it. This
- * process continues until all windows are closed. Then the gQuitting global
- * variable is set to true, terminating the main event loop.
- \******************************************************************************/
-
- void DoQuit()
- {
- WindowPtr aWindow; /* Pointer to each window in the window list */
-
- aWindow = FrontWindow();
-
- /* Keep closing a window until there are no windows left */
- while (aWindow != nil)
- {
- if (IsDAWindow( aWindow ))
- CloseDeskAcc( ((WindowPeek)aWindow)->windowKind );
- else
- CloseWindow( aWindow );
- aWindow = FrontWindow();
- }
-
- /* Tell the main event loop that we’re done */
- gQuitting = true;
- }
-
-
- /******************************************************************************\
- * Public: IsDAWindow
- *
- * The windowKind field of any window belonging to a desk accessory is negative,
- * so that’s how IsDAWindow decides whether a window belongs to a desk accessory
- * or not.
- \******************************************************************************/
-
- Boolean IsDAWindow(
- WindowPtr aWindow) /* Pointer to the window being tested */
- {
- if (aWindow == nil)
- return false;
- else
- return ((WindowPeek)aWindow)->windowKind < 0;
- }
-
-
- /******************************************************************************\
- * Private: DoWindowDrag - Allow the user to drag a window around
- *
- * When it’s been detected that the user clicked in the title bar of a window,
- * DoWindowDrag is called. It allows the user to drag a window over the entire
- * desktop area, and the window is moved to wherever the user let it go. Windows
- * behind the front window can be dragged as well, unless the front window is a
- * modal dialog box.
- *
- * The mouseDown event that turned out to be a request to drag the window is
- * passed in the anEvent parameter. A pointer to the window whose title bar got
- * clicked is passed in clickedWindow.
- *
- * A rectangle that covers all screen can be retrieved from the desktop region’s
- * rgnBBox. The desktop region can be retrieved by calling GetGrayRgn.
- \******************************************************************************/
-
- static void DoWindowDrag(
- EventRecord *anEvent, /* Mouse-down event in the title bar */
- WindowPtr clickedWindow) /* Pointer to the window that was clicked */
- {
- Rect dragBounds; /* Window can be dragged over this rectangle */
-
- /* (**GetGrayRgn()).rgnBBox covers the desktop over all screens */
- dragBounds = (**GetGrayRgn()).rgnBBox;
- DragWindow( clickedWindow, anEvent->where, &dragBounds );
- }
-
-
- /******************************************************************************\
- * Private: DoWindowGrow - Handle a mouse click in the grow box of a window
- *
- * When it’s been detected that the user clicked in the grow box of a window,
- * DoWindowGrow is called. It allows the user to change the size of the clicked
- * window.
- *
- * The mouseDown event that turned out to be a request to resize the window is
- * passed in the anEvent parameter. A pointer to the window whose grow box got
- * clicked is passed in clickedWindow.
- \******************************************************************************/
-
- static void DoWindowGrow(
- EventRecord *anEvent, /* Mouse-down event in the title bar */
- WindowPtr clickedWindow) /* Pointer to the window that was clicked */
- {
- /* Have the window react to the resize */
- if (IsPictDocWindow( clickedWindow ))
- GrowPictDoc( clickedWindow, anEvent );
- }
-
-
- /******************************************************************************\
- * Private: DoContentClick - Handle a click in a window
- *
- * When it’s been detected that the user clicked in the content region of a
- * window, DoContentClick is called. This routine determines the kind of window
- * that was clicked and dispatches control to the routine that handles mouse
- * clicks in that kind of window.
- *
- * The mouseDown event that turned out to be a window content click is passed
- * in the anEvent parameter. A pointer to the window whose content region got
- * clicked is passed in clickedWindow.
- *
- * As new kinds of windows are added to this application, this routine will have
- * to be able to detect the new kind of window and dispatch to the routine that
- * handles clicks in that kind of window.
- \******************************************************************************/
-
- static void DoContentClick(
- EventRecord *anEvent, /* Mouse-down event in the window’s content */
- WindowPtr clickedWindow) /* Pointer to the window that was clicked */
- {
- #pragma unused(anEvent)
- WindowPtr currWindow; /* Pointer to the current front window */
-
- currWindow = FrontWindow();
-
- /* Clicked window not in front; activate it */
- if (currWindow != clickedWindow)
- SelectWindow( clickedWindow );
- else
- {
- if (IsPictDocWindow( clickedWindow ))
- ClickPictDoc( clickedWindow, anEvent );
- }
- }
-
-
- /******************************************************************************\
- * Public: DoUpdateEvt
- *
- * As new kinds of windows are added to this application, this routine will have
- * to be able to detect the new kind of window and dispatch to the routine that
- * handles update events in that kind of window.
- \******************************************************************************/
-
- void DoUpdateEvt(
- EventRecord *anEvent) /* Update event */
- {
- WindowPtr eventWindow; /* Pointer to the window to update */
-
- /* Get a pointer to the window that needs an update */
- eventWindow = (WindowPtr)anEvent->message;
-
- /* Update the window that needs it */
- SetPort( eventWindow );
- BeginUpdate( eventWindow );
- if (IsPictDocWindow( eventWindow ))
- DrawPictDoc( eventWindow );
- EndUpdate( eventWindow );
- }
-
-
- /******************************************************************************\
- * Public: DoActivateEvt
- *
- * As new kinds of windows are added to this application, this routine will have
- * to be able to detect the new kind of window and dispatch to the routine that
- * handles activate events in that kind of window.
- \******************************************************************************/
-
- void DoActivateEvt(
- WindowPtr eventWindow, /* Window being (de)activated */
- Boolean becomingActive) /* True if window is becoming activated */
- {
- if (IsPictDocWindow( eventWindow ))
- ActivatePictDoc( eventWindow, becomingActive );
- }
-
-
- /******************************************************************************\
- * Private: DoWindowClose - Handle a click in the close box of a window
- *
- * This routine should be called when the user clicks in the close box of the
- * window specified by eventWind. The mouse is tracked until the user releases
- * the mouse button. If the user released the mouse button while the mouse was
- * in the close box, then DoCloseDoc determines the kind of window that the user
- * clicked the close box on, and the routine that handles the closing of that
- * kind of window is called. anEvent contains the mouse-down event that was
- * determined to be a mouse click in the window.
- *
- * As new kinds of windows are added to this application, this routine will have
- * to be able to detect the new kind of window and dispatch to the routine that
- * handles close requests for that kind of window.
- \******************************************************************************/
-
- static void DoWindowClose(
- EventRecord *anEvent, /* Mouse-down event in the close box */
- WindowPtr eventWindow) /* Pointer to the window that was clicked */
- {
- if (TrackGoAway( eventWindow, anEvent->where ))
- if (IsPictDocWindow( eventWindow ))
- DoClosePictDoc( eventWindow );
- }
-
-
- /******************************************************************************\
- * Public: ShowAlert
- *
- * To position the alert before it’s displayed, the ALRT resource is loaded
- * before it’s displayed, and its boundsRect is put into the proper position
- * through the CenterScreenRect routine. Because this modifies the ALRT
- * resource in memory and because ALRT resources are normally purgeable, it must
- * be made unpurgeable until the alert is dismissed.
- \******************************************************************************/
-
- short ShowAlert(
- short alertType, /* Type of alert to display */
- short buttonOption, /* Button options for alert */
- short messageClass, /* Class of message to display in alert */
- short messageIndex) /* Index of message to display in alert */
- {
- Str255 aMessage; /* Contents of message to place in alert */
- AlertTHndl alertHandle; /* Handle to the 'ALRT' resource for this alert */
- Rect alertRect; /* Rectangle of alert */
- short itemHit; /* Item number of clicked item */
- SignedByte savedState; /* Saves state alertHandle */
-
- /* Put the specified message into the dialog parameter text */
- if (messageIndex != 0)
- {
- GetIndString( /*<*/aMessage, messageClass, messageIndex );
- ParamText( aMessage, "\P", "\P", "\P" );
- }
-
- /* Show the stop alert */
- InitCursor();
-
- /* Center and display the alert */
- alertHandle = (AlertTHndl)Get1Resource( 'ALRT', buttonOption );
- if (alertHandle != nil)
- {
- /* Must make alert unpurgeable because we’re modifying it in memory */
- savedState = HGetState( (Handle)alertHandle );
- HNoPurge( (Handle)alertHandle );
-
- /* Put the rectangle of the alert into alert position */
- alertRect = (**alertHandle).boundsRect;
- PositionScreenRect( /*◊*/&alertRect, kMainScreenPos, kAlertPos,
- nil, 0, 0 );
- (**alertHandle).boundsRect = alertRect;
-
- /* Present the alert */
- if (alertType == kGenericAlert)
- itemHit = Alert( buttonOption, nil );
- else if (alertType == kNoteAlert)
- itemHit = NoteAlert( buttonOption, nil );
- else if (alertType == kCautionAlert)
- itemHit = CautionAlert( buttonOption, nil );
- else if (alertType == kStopAlert)
- itemHit = StopAlert( buttonOption, nil );
-
- /* Restore the state of alertHandle */
- HSetState( (Handle)alertHandle, savedState );
- }
-
- return itemHit;
- }
-
-
- /******************************************************************************\
- * Public: TrapExists
- *
- * Traps with trap word of $AAXX or $ABXX are treated as being identical to $A8XX
- * and $A9XX if Color QuickDraw isn’t implemented, so we check for this case
- * first. We explicitly check to see if the trap word has a value greater than
- * the largest possible trap word on this machine. If it is, then the trap is
- * automatically considered to be unimplemented.
- \******************************************************************************/
-
- Boolean TrapExists(
- short theTrap) /* Trap word being tested */
- {
- TrapType theTrapType; /* The trap type of theTrap */
-
- /* If it’s a CQD trap but the trap table is too small, assume unimp. */
- theTrapType = GetTrapType( theTrap );
- if ((theTrapType == ToolTrap) && ((theTrap &= 0x07FF) >=
- MaxToolboxTrap()))
- theTrap = _Unimplemented;
-
- /* Return true if trap is implemented */
- return NGetTrapAddress( _Unimplemented, ToolTrap ) !=
- NGetTrapAddress( theTrap, theTrapType );
- }
-
-
- /******************************************************************************\
- * Private: MaxToolboxTrap - Determine max trap number available
- *
- * Depending upon whether Color QuickDraw is implemented, the maximum trap number
- * is either $0200 or $0400. This routine tests to see which is the case by
- * testing _InitGraf (trap $A86E) against trap $AA6E. If the trap table is the
- * bigger one, trap $AA6E always points either to Unimplemented or some other
- * trap. If the trap table is the smaller one, then $AA6E evaluates to the same
- * trap as _InitGraf. by comparing the address of the InitGraf trap against the
- * address of the $AA6E trap, we can determine whether the trap table is the
- * bigger one or the smaller one. If we have the bigger trap table, then $0400
- * is returned. If it’s the smaller trap table, then $0200 is returned.
- *
- * Some of you might think that it’s be a lot simpler by testing to see whether
- * Color QuickDraw is implemented or not. Actually, I kind of think so too, but
- * there are changes to the system software version 7.0 trap dispatcher that
- * might make that test invalid, so I don’t know. I didn’t write this, I just
- * use it.
- \******************************************************************************/
-
- static short MaxToolboxTrap()
- {
- if (NGetTrapAddress( _InitGraf, ToolTrap ) ==
- NGetTrapAddress(0xAA6E, ToolTrap))
- return 0x0200;
- else
- return 0x0400;
- }
-
-
- /******************************************************************************\
- * Private: GetTrapType - Determine whether a trap is OS trap or Toolbox trap
- *
- * This routine tests to see whether the trap specified by theTrap is an
- * operating system trap or a toolbox trap. Operating system trap words begin
- * with $A0 or $A1 while toolbox traps begin with $A8, $A9, $AA, or $AB. By
- * simply testing bit 11 of the trap word, we can determine which kind of trap
- * theTrap is. If it’s an operating system trap, then OSTrap is returned. If
- * it’s a toolbox trap, then ToolTrap is returned.
- \******************************************************************************/
-
- static TrapType GetTrapType(
- short theTrap) /* Trap word being tested */
- {
- /* OS traps start with A0 or A1, Toolbox traps with A8, A9, AA, or AB */
- if ((theTrap & 0x0800) == 0)
- return OSTrap;
- else
- return ToolTrap;
- }
-
-
- /******************************************************************************\
- * Public: FileSpecGet
- *
- *
- \******************************************************************************/
-
- Boolean FileSpecGet(
- FileFilterProcPtr fileFilter, /* Pointer to routine to filter files */
- short numTypes, /* Number of files types in typeList */
- SFTypeList typeList, /* Type of files to offer */
- StandardFileReply *retReply) /* Returns information about file to get */
- {
- DialogTHndl sfTemplate; /* Template for Standard File dialog */
- Rect sfRect; /* Rectangle of Standard File dialog */
- SFReply oldReply; /* Old-style reply record */
-
- if (gHasCoolSF)
- StandardGetFile( fileFilter, numTypes, typeList, /*<*/retReply );
- else
- {
- /* Center the rectangle of the Standard File dialog */
- sfTemplate = (DialogTHndl)GetResource( 'DLOG', getDlgID );
- sfRect = (**sfTemplate).boundsRect;
- PositionScreenRect( &sfRect, kMainScreenPos, kAlertPos,
- nil, 0, 0 );
-
- /* Present the Standard File dialog */
- SFGetFile( topLeft( sfRect ), "\P", fileFilter, numTypes, typeList, nil,
- /*<*/&oldReply );
-
- /* Convert the old reply to a new reply record */
- (void)ConvertOldToNewSFReply( &oldReply, retReply );
- }
- return retReply->sfGood;
- }
-
-
- /******************************************************************************\
- * Public: ConvertOldToNewSFReply
- *
- * GetWDInfo is used to convert the working directory reference number that’s
- * in the oldReply->vRefNum field to a real volume reference number and directory
- * ID so that these values can be stuffed into the new reply record’s FSSpec.
- \******************************************************************************/
-
- OSErr ConvertOldToNewSFReply(
- SFReply *oldReply, /* Old reply record to be converted */
- StandardFileReply *newReply) /* Returns the converted reply record */
- {
- short volRef; /* Volume ref number (NOT WD ref num) of file */
- long dirID; /* Directory ID of the file */
- long procID; /* WD Proc ID; ignored */
- FInfo finderInfo; /* Finder info for a file; ignored */
- Boolean replacing; /* True if the specified file exists */
- OSErr error;
-
- /* Get the real volume reference number of directory ID of file */
- error = GetWDInfo( oldReply->vRefNum, /*<*/&volRef,
- /*<*/&dirID, /*<*/&procID );
- if (error != noErr)
- return error;
-
- /* Probe to see if the specified file exists */
- error = HGetFInfo( volRef, dirID, oldReply->fName, /*<*/&finderInfo );
- if (error == fnfErr)
- replacing = false;
- else if (error == noErr)
- replacing = true;
- else
- return error;
-
- /* Fill out the new reply record */
- newReply->sfGood = oldReply->good;
- newReply->sfReplacing = replacing;
- newReply->sfType = oldReply->fType;
- newReply->sfFile.vRefNum = volRef;
- newReply->sfFile.parID = dirID;
- BlockMove( (Ptr)&oldReply->fName, (Ptr)&newReply->sfFile.name,
- oldReply->fName[0] + 1 );
- newReply->sfScript = iuSystemScript;
- newReply->sfFlags = 0;
- newReply->sfIsFolder = false;
- newReply->sfIsVolume = false;
- newReply->sfReserved1 = 0;
- newReply->sfReserved2 = 0;
-
- return noErr;
- }
-
-
- /******************************************************************************\
- * Public: EqualFSSpec
- *
- * To compare names, I’m using EqualString with no case sensitivity, but with
- * sensitivity to diacriticals. This isn’t usually the recommended way of
- * comparing strings, because the Script Manager has routines for comparing
- * strings in a more sophisticated, localizable way. But the File Manager uses
- * _CmpString, which is the assembly language equivalent of EqualString, so
- * that’s the way I must do things here.
- \******************************************************************************/
-
- Boolean EqualFSSpec(
- FSSpecPtr spec0, /* First FSSpec being compared */
- FSSpecPtr spec1) /* Second FSSpec being compared */
- {
- return (spec0->vRefNum == spec1->vRefNum) &&
- (spec0->parID == spec1->parID) &&
- (EqualString(spec0->name, spec1->name, !kCaseSens, kDiacSens));
- }
-
-
- /******************************************************************************\
- * Public: CmdPeriodEvent
- *
- * This routine uses the technique documented in Macintosh Technical Note #263
- * to determine whether the event passed in the anEvent parameter contains a
- * command-period event or not, regardless of the current keyboard layout.
- *
- * The problem that this routine solves is that some keyboards (mainly some
- * European keyboards) require the shift key to be pressed to generate the
- * period, but the command key turns off the shift key, making it impossible to
- * see the period. To fix this, this routine calls the KeyTrans routine which
- * maps a virtual keycode and modifier keys to the ASCII code of the typed
- * character. The modifier keys passed to KeyTrans are the same as in the
- * event record, but the command key modifier bit is stripped out. This makes
- * KeyTrans think the command key wasn’t held down, and so the influence of other
- * modifier keys is unaffected.
- \******************************************************************************/
-
- Boolean CmdPeriodEvent(
- EventRecord *anEvent) /* Event being tested */
- {
- long lowChar; /* Low character of keyInfo */
- long highChar; /* High character of keyInfo */
- Handle hKCHR; /* Handle to the currently-used KCHR */
- long keyInfo; /* Key information returned from KeyTrans */
- long keyScript; /* Script of the current keyboard */
- long state; /* State used for KeyTrans */
- short virtualKey; /* Virtual keycode of the character-generating key */
- short keyCode; /* Keycode of the character-generating key */
- Boolean gotCmdPeriod; /* True if detected command-. */
-
- gotCmdPeriod = false;
- if (anEvent->what == keyDown || anEvent->what == autoKey)
- {
- if (anEvent->modifiers & cmdKey)
- {
- /* Get the virtual keycode of the code-generating key */
- virtualKey = (anEvent->message & keyCodeMask) >> 8;
-
- /* Get a copy of the current KCHR */
- keyScript = GetScript( GetEnvirons( smKeyScript ), smScriptKeys);
- hKCHR = GetResource('KCHR', keyScript);
- if (hKCHR != nil)
- {
- /* AND out the command key and OR in the virtualKey */
- keyCode = (anEvent->modifiers & kMaskModifiers) | virtualKey;
-
- /* Get key information */
- state = 0;
- keyInfo = KeyTrans( *hKCHR, keyCode, &state );
- }
- else
- keyInfo = anEvent->message;
-
- /* Check both low and high bytes of keyInfo for period */
- lowChar = keyInfo & kMaskASCII2;
- highChar = (keyInfo & kMaskASCII1) >> 16;
- if (lowChar == '.' || highChar == '.')
- gotCmdPeriod = true;
- }
- }
-
- return gotCmdPeriod;
- }
-
-
- /******************************************************************************\
- * Public: FakeButtonHit
- *
- * HiliteControl is used to hilight and unhilight a button.
- \******************************************************************************/
-
- void FakeButtonHit(
- ControlHandle buttonControl) /* Handle to button whose click we’re faking */
- {
- long lastTicks; /* TickCount at end of delay; ignored */
-
- HiliteControl( buttonControl, 1 );
- Delay( 6, &lastTicks );
- HiliteControl( buttonControl, 0 );
- }
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * RestoreColorsPalette: Restore all screens to the default color table
- *
- * PARAMETERS:
- * See ColorReset.h
- *
- * DEFINITION:
- * See ColorReset.h
- *
- * DESCRIPTION:
- * To change the color table of any screen using the Palette Manager, a window
- * must be used. But all we want to do is reset the color tables, not display a
- * window. The obvious solution is to make a very small, inconspicuous window
- * that’s tough to notice, and that’s what RestoreColorsPalette does. A 1 pixel
- * by 1 pixel is created, and a 1-entry palette is made and attached to the
- * window, just so that it has a palette that can be set to the right size and
- * colors later.
- *
- * Each screen can have different depths, and each can be gray-scale or colors,
- * so every screen has have its colors set individually. Since all we have is a
- * 1 pixel by 1 pixel window, there’s not much choice here anyway. To run
- * through each screen, the GDevice list is used. The GDevice list is a linked
- * list of GDevice records that the system maintains, and there’s one GDevice
- * record for every screen that’s attached to a Macintosh. Each screen’s GDevice
- * can be used to find out the screen’s depth, and whether it’s set to Grays or
- * Colors mode. See the Graphics Device Manager chapter of Inside Macintosh
- * Volume VI for details. GetDeviceList is used to find the first GDevice in the
- * GDevice list, and GetNextDevice is used to get the next GDevice list the list.
- *
- * For each GDevice in the list, it’s first tested to see if it belongs to an
- * active screen. If it doesn’t, then we just ignore it and go to the next
- * GDevice in the list. If it does, then the GDevice’s PixMap is checked to see
- * what the depth of the screen is. This depth can be passed to the GetCTable
- * routine (see the Color Manager chapter of Inside Macintosh Volume V for
- * details about this routine) to get a color table filled with the default
- * colors for the screen depth. As of 32-Bit QuickDraw 1.0 and/or system
- * software version 6.0.5, the color table of a screen is guaranteed to contain
- * the highlight color, and if you add 64 to the pixel depth and pass the result
- * to GetCTable, GetCTable returns a color table filled with the default colors
- * including the highlight color, and so that’s what I pass to GetCTable for a
- * screen set to Colors mode. For gray-scale screens, you add 32 to the pixel
- * depth to have GetCTable return a color table filled with the default gray-
- * scale color table.
- *
- * I pass whatever color table GetCTable returns to CTab2Palette, and I use a
- * usage mode of pmTolerant + pmExplicit. This mode is just like pmTolerant, but
- * it guarantees that the palette colors are put into the screen’s color table in
- * the same order that they appear in the palette when that palette is activated.
- * If you just use pmTolerant, the order of colors in the screen’s color table
- * will likely be scrambled, so the screen has the default colors, but not in the
- * default order.
- *
- * Once the palette is set up with the default colors for the screen we’re
- * working on, the 1 pixel by 1 pixel window is moved to the extreme upper-left
- * corner of the screen, then it’s shown and immediately hidden. The moment the
- * window is shown, the screen’s color table is filled with the default colors in
- * the default order. Then we move on to the next screen until all screens have
- * been handled.
- *
- * RETURN VALUES:
- * See ColorReset.h
- \******************************************************************************/
-
- void RestoreColorsPalette()
- {
- WindowPtr tinyWindow; /* Pointer to tiny window */
- CTabHandle defaultColors; /* Default color table for the screen */
- PaletteHandle tinyPalette; /* Palette to express defaultColors */
- Rect tinyRect; /* Rectangle of tiny window */
- GDHandle screenDevice; /* Handle to each screen’s GDevice */
- Point screenCorner; /* Global coordinate of top-left of each screen */
- short clutID; /* ID of table of default colors */
-
- /* Make the tiny window for attaching our palette */
- SetRect( &tinyRect, 0, 0, 1, 1 );
- tinyWindow = NewCWindow(
- nil,
- &tinyRect,
- "\P",
- false,
- plainDBox,
- (WindowPtr)-1,
- false,
- 0L );
-
- /* Make a palette; it’s just a placeholder for the moment */
- tinyPalette = NewPalette( 1, nil, pmTolerant + pmExplicit, 0 );
- SetPalette( tinyWindow, tinyPalette, false );
-
- /* Loop through each screen GDevice to reset its screen’s colors */
- screenDevice = GetDeviceList();
- while (screenDevice != nil)
- {
- if (TestDeviceAttribute( screenDevice, screenActive ))
- {
- /* Grab default color table for the screen */
- clutID = (**(**screenDevice).gdPMap).pixelSize;
- if (TestDeviceAttribute (screenDevice, gdDevType ))
- clutID += 64;
- else
- clutID += 32;
- defaultColors = GetCTable( clutID );
-
- /* Convert default screen colors to a tolerant palette */
- CTab2Palette( defaultColors, tinyPalette, pmTolerant + pmExplicit, 0 );
-
- /* Don’t need that clut any more */
- DisposeCTable( defaultColors );
-
- /* Move the tiny window into the upper left corner of the screen */
- screenCorner = topLeft( (**screenDevice).gdRect );
- MoveWindow( tinyWindow, screenCorner.h, screenCorner.v, false );
- ShowWindow( tinyWindow );
- HideWindow( tinyWindow );
- }
-
- /* Go to the next screen in the device list */
- screenDevice = GetNextDevice( screenDevice );
- }
-
- /* Get rid of the window and palette */
- DisposePalette( tinyPalette );
- DisposeWindow( tinyWindow );
- }
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * RestoreColorsSlam: Restore all screens to the default color table
- *
- * PARAMETERS:
- * See ColorReset.h
- *
- * DEFINITION:
- * See ColorReset.h
- *
- * DESCRIPTION:
- * 32-Bit QuickDraw 1.0 and system software version 6.0.5 introduced a new
- * routine called RestoreDeviceClut which sets the color table of specific
- * screens or all the screens to the default set of colors. RestoreColorsSlam
- * calls RestoreDeviceClut with a nil parameter, which restores the color table
- * of all attached screens. At this point, the screen could appear in strange
- * colors because RestoreDeviceClut doesn’t cause update events to cause the
- * screen to be redrawn in the new colors. So, RestoreColorsSlam forces all the
- * screens to be redrawn by calling the Window Manager routine, PaintBehind.
- * This causes the entire desktop area and all windows to be redrawn. The only
- * part of the screen that isn’t guaranteed to be redrawn is the menu bar, so
- * DrawMenuBar is called to make sure the menu bar is redrawn in the new colors.
- *
- * RETURN VALUES:
- * See ColorReset.h
- \******************************************************************************/
-
- void RestoreColorsSlam()
- {
- RestoreDeviceClut( nil );
- PaintBehind( nil, GetGrayRgn() );
- DrawMenuBar();
- }
-